package com.jandar.pile.common.util;

import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author : cyt
 * @date : 2019/3/4
 */
public class ParamBundle implements IParamBundle {

    private final Map<String, Object> param;
    private final DateFormat defaultFormat;

    private ParamBundle(Map<String, Object> param) {
        this.param = param;
        this.defaultFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    }

    private ParamBundle(Map<String, Object> param, String format) {
        this.param = param;
        this.defaultFormat = new SimpleDateFormat(format);
    }

    public static IParamBundle newBundle(Map<String, Object> param) {
        return new ParamBundle(param);
    }

    public static IParamBundle newBundle(Map<String, Object> param, String format) {
        return new ParamBundle(param, format);
    }

    @Override
    public List<Integer> getIntegerList(String key) {
        if (param.containsKey(key)) {
            JSONArray arr = JSONArray.parseArray(String.valueOf(param.get(key)));
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < arr.size(); i++) {
                list.add(arr.getInteger(i));
            }


            return list;
        }
        return new ArrayList<>();
    }

    @Override
    public String getString(String key) {
        return getString(key, "", null);
    }

    @Override
    public String getString(String key, String defVal) {
        return getString(key, defVal, null);
    }

    @Override
    public String getString(String key, ParamFilter<String> paramFilter) {
        return getString(key, "", paramFilter);
    }

    @Override
    public String getString(String key, String defVal, ParamFilter<String> paramFilter) {
        if (param.containsKey(key)) {
            String value = param.get(key).toString();
            if (paramFilter != null) {
                return paramFilter.filter(value);
            }
            return value;
        }
        return defVal;
    }

    @Override
    public Integer getInt(String key) {
        return getInt(key, 0, null);
    }

    @Override
    public Integer getInt(String key, Integer defVal) {
        return getInt(key, defVal, null);
    }

    @Override
    public Integer getInt(String key, ParamFilter<Integer> paramFilter) {
        return getInt(key, 0, paramFilter);
    }

    @Override
    public Integer getInt(String key, Integer defVal, ParamFilter<Integer> paramFilter) {
        if (param.containsKey(key)) {
            Integer value = Integer.parseInt(param.get(key).toString());
            if (paramFilter != null) {
                return paramFilter.filter(value);
            }
            return value;
        }
        return defVal;
    }

    @Override
    public Boolean getBoolean(String key) {
        return getBoolean(key, false, null);
    }

    @Override
    public Boolean getBoolean(String key, Boolean defVal) {
        return getBoolean(key, defVal, null);
    }

    @Override
    public Boolean getBoolean(String key, ParamFilter<Boolean> paramFilter) {
        return getBoolean(key, false, paramFilter);
    }

    @Override
    public Boolean getBoolean(String key, Boolean defVal, ParamFilter<Boolean> paramFilter) {
        if (param.containsKey(key)) {
            Boolean value = Boolean.parseBoolean(param.get(key).toString());
            if (paramFilter != null) {
                return paramFilter.filter(value);
            }
            return value;
        }
        return defVal;
    }

    @Override
    public Double getDouble(String key) {
        return getDouble(key, 0.0, null);
    }

    @Override
    public Double getDouble(String key, Double defVal) {
        return getDouble(key, defVal, null);
    }

    @Override
    public Double getDouble(String key, ParamFilter<Double> paramFilter) {
        return getDouble(key, 0.0, paramFilter);
    }

    @Override
    public Double getDouble(String key, Double defVal, ParamFilter<Double> paramFilter) {
        if (param.containsKey(key)) {
            Double value = Double.parseDouble(param.get(key).toString());
            if (paramFilter != null) {
                return paramFilter.filter(value);
            }
            return value;
        }
        return defVal;
    }

    @Override
    public Long getLong(String key) {
        return getLong(key, 0L, null);
    }

    @Override
    public Long getLong(String key, Long defVal) {
        return getLong(key, defVal, null);
    }

    @Override
    public Long getLong(String key, ParamFilter<Long> paramFilter) {
        return getLong(key, 0L, paramFilter);
    }

    @Override
    public Long getLong(String key, Long defVal, ParamFilter<Long> paramFilter) {
        if (param.containsKey(key)) {
            Long value = Long.parseLong(param.get(key).toString());
            if (paramFilter != null) {
                return paramFilter.filter(value);
            }
            return value;
        }
        return defVal;
    }

    @Override
    public List<Long> getLongList(String key) {
        return getLongList(key, new ArrayList<>(), null);
    }

    @Override
    public List<Long> getLongList(String key, List<Long> defVal) {
        return getLongList(key, defVal, null);
    }

    @Override
    public List<Long> getLongList(String key, ParamFilter<List<Long>> paramFilter) {
        return getLongList(key, new ArrayList<>(), paramFilter);
    }


    @Override
    public List<Long> getLongList(String key, List<Long> defVal, ParamFilter<List<Long>> paramFilter) {
        if (param.containsKey(key)) {
            long[] arr = (long[]) param.get(key);
            List<Long> list = new ArrayList<>();
            for (long a : arr) {
                list.add(a);
            }
            if (paramFilter != null) {
                return paramFilter.filter(list);
            }
            return list;
        }
        return defVal;
    }

    @Override
    public Date getDate(String key) {
        return getDate(key, "", null);
    }

    @Override
    public Date getDate(String key, String format) {
        return getDate(key, format, null);
    }

    @Override
    public Date getDate(String key, ParamFilter<Date> paramFilter) {
        return getDate(key, "", paramFilter);
    }

    @Override
    public Date getDate(String key, String format, ParamFilter<Date> paramFilter) {
        Date date = null;
        try {
            Object dateStr = param.get(key);
            if (dateStr == null) {
                return null;
            }
            if (StringUtils.isNotBlank(format)) {
                DateFormat dateFormat = new SimpleDateFormat(format);
                date = dateFormat.parse(dateStr.toString());
            } else {
                date = defaultFormat.parse(dateStr.toString());
            }
            if (paramFilter != null) {
                return paramFilter.filter(date);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    @Override
    public <T> T get(String key, T defVal) {
        return get(key, defVal, null);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> T get(String key, T defVal, ParamFilter<T> paramFilter) {
        if (param.containsKey(key)) {
            if (paramFilter != null) {
                return paramFilter.filter((T) param.get(key));
            }
            return (T) param.get(key);
        }
        return defVal;
    }

    @Override
    public Map<String, Object> getParam() {
        return param;
    }

    @Override
    public PageBundle getPageBundle() {
        return getPageBundle("page", 1, "size", 10);
    }

    @Override
    public PageBundle getPageBundle(String pageName, String sizeName) {
        return getPageBundle(pageName, 1, sizeName, 10);
    }

    @Override
    public PageBundle getPageBundle(int pageDefVal, int sizeDefVal) {
        return getPageBundle("page", pageDefVal, "size", sizeDefVal);
    }

    @Override
    public PageBundle getPageBundle(String pageName, int pageDefVal, String sizeName, int sizeDefVal) {
        int page = getInt(pageName, pageDefVal);
        int size = getInt(sizeName, sizeDefVal);
        return PageBundle.builder()
                .page(page)
                .size(size)
                .start((page - 1) * size)
                .build();
    }
}
